//***************************************************************
//
// Created BY: JESSE SAHOTA & Jared
// COURSE: CPSC 589
//
//***************************************************************
#ifndef PLANT_H
#define PLANT_H

#include "Vector.h"
#include <vector>
#include <cstdlib>
#include "Branch.h"

class pointASpace{
public:
    pointASpace() : closestSegment(NULL){}
    pointASpace(Point3d p) : position(p),closestSegment(NULL){}
   // ~pointASpace(){closestSegment = NULL;}
    Point3d position;
    Branch * closestSegment;
    double closestDistance;
};
class Plant
{
    public:
        Plant();
        ~Plant();

	
        void generateAttractionPoints();
	void generateAttractionPointsReg();
        void generateAttractionPointsPine();

        void draw();

        void grow();

        void update();
        void loadFile(string filename);
        bool saveFile(string filename);
        void delete_tree(Branch * segment);


        void setTreeSize(double newEXP);
        void setRadiusOfInfl(double val);
	double getRadiusOfInfl()const;
        void setTreeType(int Id);
        void setDrawType(int Id);

	void setTropismFactor(double tropCoeff);
	double getTropismFactor()const;

        void setKillDistance(double val);
        double getKillDistance();

        void setShowTexture(bool check);

        void initTexture(const int & height,const int & width, unsigned char * bits);
    private:
        bool textureLoaded;
        bool showTexture;
        GLuint treeTexture;

        vector<pointASpace> attractPoints;
        double killDistance; //can be changeable for different type of plants
	int initialTotalSize;
        Branch * tree;
        double PIPE_EXP;
        double MAX_DISTANCE;//radius of influcence is used for the max distance
        //between the closest segment of the attraction point and the node's end point

	double tropFactor;
        enum {REGULAR , PINE} treeType;
        enum {SKELETON, WIREFRAME, SMOOTH} drawType;

        void init_tree();
        bool isEmpty(Branch * segment);

        void drawAttractionPoints();
        void drawTreeAndTraverse(Branch *segment);
        void drawLeaves(Branch *segment);
        void drawNeedles(Branch *segment);
        void drawSkeletonTree(Branch * segment);
        void drawSmoothTree(Branch * segment);
        void drawWireFrameTree(Branch * segment);
        double updateTreeAndTraverse(Branch * segment);

        void traverseAndGrow(Branch * segment);
        void traverseAndSelectClosestNode(Branch * segment, pointASpace & aPoint);
        void traverseAndSelectClosestNodePine(Branch * segment, pointASpace & aPoint);

	void determineThresholdPoint(unsigned int & i);

        void drawTreeAndTraverse2(Branch * segment);
        void assignWeight(Branch * segment);
};


//Returns a random value between -1 and 1
inline double getRand()
{
    return (2.0*(float)rand()/static_cast<double>(RAND_MAX) - 1.0);

}

#endif // PLANT_H

